import Cesium from '../../Ces/Cesium';
import SuperGif from 'libgif';

function setDataTransparent(imgData) {
  const count = imgData.width * imgData.height;

  for (let i = 0; i < count; i++) {
    const r = imgData.data[i * 4 + 0];
    const g = imgData.data[i * 4 + 1];
    const b = imgData.data[i * 4 + 2];

    imgData.data[i * 4 + 0] = r;
    imgData.data[i * 4 + 1] = g;
    imgData.data[i * 4 + 2] = b;
    imgData.data[i * 4 + 3] = (r < 8 || g === 0 || b === 0) ? 0 : 255;
  }

  return imgData;
}

function GifBillboard(options) {
  this.WE = options.WE;
  this.useSystemTime = options.useSystemTime?? true
  const that = this;
  const url = options.url;

  this.duration = 1.0;

  this._billboards = new Cesium.BillboardCollection({
    debugShowTextureAtlas: false,
  });

  this._readyPromise = Cesium.defer();

  const div = document.createElement('div');
  const img = document.createElement('img');

  img.setAttribute('rel:animated_src', url);
  img.setAttribute('rel:auto_play', '0');
  div.appendChild(img);
  const rub = new SuperGif({ gif: img });

  rub.load_url(url, () => {
    that.duration = rub.get_duration_ms() * 0.001;
    that.setFrames(rub.get_frames());
    that._readyPromise.resolve(that);
  });
  this._div = div;

  this._updater = [
    {
      frameIndex: 0,
      lastUpdateTime: 0,
    },
    {
      frameIndex: 0,
      lastUpdateTime: 0,
    },
    {
      frameIndex: 0,
      lastUpdateTime: 0,
    },
    {
      frameIndex: 0,
      lastUpdateTime: 0,
    },
  ];

  this.gifWidth = 0;
  this.gifHeight = 0;
}

GifBillboard.modify = setDataTransparent;

Object.defineProperties(GifBillboard.prototype, {
  billboard: {
    get() {
      return this._billboard;
    },
  },
  billboards: {
    get() {
      return this._billboards;
    },
  },
  readyPromise: {
    get() {
      return this._readyPromise.promise;
    },
  },
});

GifBillboard.prototype.add = function (options) {
  const billboard = this._billboards.add(
    options,
  );

  const imageID = this._billboards.length % 4;
  // const imageID = 1;

  billboard.setImage(imageID, this.getFrame(0).data);

  return billboard;
};

GifBillboard.prototype.getFrame = function (i) {
  return this.frames[i];
};

GifBillboard.prototype.setFrames = function (frames) {
  this.gifWidth = frames[0].data.width;
  this.gifHeight = frames[0].data.height;

  frames.forEach((element) => {
    GifBillboard.modify(element.data);
  });

  for (let i = 0; i < this._updater.length; i++) {
    const updater = this._updater[i];

    updater.frameIndex = Math.floor(frames.length / this._updater.length * i);
    updater.lastUpdateTime = this.useSystemTime ? Cesium.JulianDate.now() : 0;
  }

  this.frames = frames;
};

GifBillboard.prototype.isdestroyed = function () {
  return false;
};

GifBillboard.prototype.destroy = function () {
  this._billboards = this._billboards && this._billboards.destroy();
};

GifBillboard.prototype.update = function (frameState) {
  if (!Cesium.defined(this.frames)) {
    return;
  }

  if (frameState.passes.render) {
    this._billboards.update(frameState);
  }

  const texture = this._billboards.textureAtlas.texture;

  const width = this.gifWidth;
  const height = this.gifHeight;

  if (texture.width > width) {
    for (let i = 0; i < this._updater.length; i++) {
      const updater = this._updater[i];
      const frame = this.getFrame(updater.frameIndex);

      let elapseTime;

      if (this.useSystemTime) {
        elapseTime = 1000 * Cesium.JulianDate.secondsDifference(frameState.time, updater.lastUpdateTime);
        if (Cesium.defined(this.WE)) {
          elapseTime /= this.WE.viewer.clock.multiplier;
        }
      } else {
        elapseTime = new Date().getTime() - updater.lastUpdateTime;
      }
      elapseTime = Math.abs(elapseTime);
      if (elapseTime > frame.delay * 10) {
        updater.frameIndex++;
        if (updater.frameIndex >= this.frames.length) {
          updater.frameIndex = 0;
        }

        const source = frame.data;

        const x = i % 2;
        const y = i > 1 ? 1 : 0;

        texture.copyFrom({
          source,
          width,
          height,
          xOffset: (x * width) + 1 + x,
          yOffset: (y * height) + 1 + y,
        });

        if (this.useSystemTime) {
          updater.lastUpdateTime = Cesium.JulianDate.clone(frameState.time, updater.lastUpdateTime);
        } else {
          updater.lastUpdateTime = new Date().getTime();
        }
      }
    }
  }
};


export default GifBillboard;
